#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
商户进件相关接口调用示例
"""

import os
import sys
import uuid
import logging

# 添加项目根目录到Python路径，确保能够导入jlpay包
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

from jlpay.base.config import OrgConfig
from jlpay.services.openmerch.register.merchant_service import MerchantService
from jlpay.model.openmerch.register.merchant import (
    MerchantIncomingAddRequest, 
    MerchantIncomingModifyRequest,
    RealnameQueryRequest
)
from jlpay.utils.log_config import configure_rotating_file_logging

# =================== 常量定义 =====================
# 产品类型常量
PRODUCT_TYPE_QR_CODE = "01"  # 扫码商户：适用于码牌类商户，支持微信/支付宝/银联二维码交易
PRODUCT_TYPE_STANDARD = "02"  # 标准商户：适用于POS类商户，支持银行卡+微信/支付宝/银联二维码交易
PRODUCT_TYPE_SCENE = "03"  # 场景商户：特定准入商户标准,以人工申请结果为准
PRODUCT_TYPE_SAAS = "04"  # SaaS商户：适用于SaaS类商户，支持微信/支付宝/银联二维码/银行卡交易

# 签约模式常量
SIGN_MODE_PAPER = "P"  # 线下纸质协议
SIGN_MODE_ELECTRONIC = "E"  # 电子签章协议
SIGN_MODE_JLPAY = "J"  # 嘉联电子协议

# 联系人类型常量
CONTACT_TYPE_LEGAL_PERSON = "65"  # 经营者/法人
CONTACT_TYPE_OPERATOR = "66"  # 经办人（经商户授权办理支付业务的人员）

# 商户身份类型常量
MERCH_TYPE_MICRO = "0"  # 小微
MERCH_TYPE_ENTERPRISE = "1"  # 营业执照、政府机关、事业单位或其他组织

# 结算类型常量
SETTLE_TYPE_LEGAL_PERSON_CARD = "01"  # 打款至法人银行卡
SETTLE_TYPE_PUBLIC_ACCOUNT = "02"  # 打款至对公账户
SETTLE_TYPE_PRIVATE_AUTHORIZED = "03"  # 对私授权收款，打款至他人银行卡
SETTLE_TYPE_PUBLIC_AUTHORIZED = "04"  # 对公授权收款，打款至他人对公账户

# 结算关系常量
SETTLE_RELATION_SHAREHOLDERS = "01"  # 股东/雇佣
SETTLE_RELATION_BRANCHES = "02"  # 总分公司
SETTLE_RELATION_PARENT_SUBSIDIARY = "03"  # 母子公司
SETTLE_RELATION_OTHER = "09"  # 其它

# 日志配置常量
LOG_FORMAT = '%(asctime)s - %(name)s - %(levelname)s - %(filename)s:%(lineno)d - %(funcName)s() - %(message)s'
MAX_LOG_SIZE = 10 * 1024 * 1024  # 10MB
MAX_BACKUP_COUNT = 10

# =================== 日志配置 =====================
# 配置日志系统，使用滚动文件处理器
log_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "logs")
root_logger = configure_rotating_file_logging(
    level=logging.INFO,
    log_dir=log_dir,
    log_name_prefix="jlpay",
    log_format=LOG_FORMAT,
    max_bytes=MAX_LOG_SIZE,
    backup_count=MAX_BACKUP_COUNT,
    propagate=True,
    module_levels={
        'jlpay.http': logging.INFO,
        'jlpay.service': logging.INFO,
        'examples': logging.INFO
    }
)

# 获取示例程序的logger实例
logger = logging.getLogger("examples.merchant_incoming")
logger.setLevel(logging.INFO)

# 全局变量,用于存储当前使用的apply_id
current_apply_id = ""

# =================== 密钥配置 =====================
# SM2公私钥
sm2_public_key_pem = """-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAEJJhFmjeMRp9GwShxtWunv6Wny//m
Dg2pcnu0llDQvIYo5O3R+al39NekciZ0BIrT21Y/QJrXgJIoyBr6STml6g==
-----END PUBLIC KEY-----"""

sm2_private_key_pem = """-----BEGIN EC PRIVATE KEY-----
MIGTAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBHkwdwIBAQQgHqOp471SMDsQml2G
2ErpZPLD2X7rbMqa6P1O9Zqlhe+gCgYIKoEcz1UBgi2hRANCAAQkmEWaN4xGn0bB
KHG1a6e/pafL/+YODalye7SWUNC8hijk7dH5qXf016RyJnQEitPbVj9AmteAkijI
GvpJOaXq
-----END EC PRIVATE KEY-----"""

# 嘉联支付平台公钥
jlpay_pub_key_pem = """-----BEGIN PUBLIC KEY-----
MIIBMzCB7AYHKoZIzj0CATCB4AIBATAsBgcqhkjOPQEBAiEA/////v//////////
//////////8AAAAA//////////8wRAQg/////v////////////////////8AAAAA
//////////wEICjp+p6dn140TVqeS89lCafzl4n1FauPkt28vUFNlA6TBEEEMsSu
LB8ZgRlfmQRGajnJlI/jC7/yZgvhcVpFiTNMdMe8Nzai9PZ3nFm9zuNraSFT0KmH
fMYqR0AC3zLlITnwoAIhAP////7///////////////9yA99rIcYFK1O79Ak51UEj
AgEBA0IABKZ3VWwH0Aw9xvOWXb+xM2gXyApWEAZLFy8UyIigp3ehOTwPJ693njrg
NavTLdzAtFBqXRreivlwBTIFy8iRgn8=
-----END PUBLIC KEY-----"""

# =================== 工具函数 =====================
def create_config():
    """创建配置对象"""
    config = OrgConfig.builder() \
        .app_id("1vzougr30f9vcw") \
        .url("https://openapi-uat.jlpay.com") \
        .org_pri_key(sm2_private_key_pem) \
        .org_pub_key(sm2_public_key_pem) \
        .jlpay_pub_key(jlpay_pub_key_pem) \
        .auto_encrypt(True) \
        .crypto_alg("SM2WithSM4") \
        .auto_decrypt(True) \
        .build()
    return config

def generate_apply_id():
    """生成唯一的apply_id"""
    global current_apply_id
    current_apply_id = f"1vzougr30f9vcw{uuid.uuid4().hex[:16]}"
    return current_apply_id

def send_request_and_handle_response(service, request, operation_name):
    """发送请求并处理响应"""
    try:
        # 根据操作类型调用不同的服务方法
        if isinstance(request, MerchantIncomingAddRequest):
            response = service.merchant_incoming_add(request)
        elif isinstance(request, MerchantIncomingModifyRequest):
            response = service.merchant_incoming_modify(request)
        elif isinstance(request, RealnameQueryRequest):
            response = service.realname_query(request)
        else:
            logger.error(f"不支持的请求类型: {type(request)}")
            return None
        
        if response.is_success():
            logger.info(f"{operation_name}成功！")
            return response
        else:
            logger.error(f"{operation_name}失败: {response.ret_code} - {response.ret_msg}")
            return None
            
    except Exception as e:
        logger.error(f"请求异常: {str(e)}")
        return None

# =================== 商户进件请求构建函数 =====================
def build_base_info(is_modify=False):
    """构建商户基础信息"""
    apply_id = current_apply_id if is_modify else generate_apply_id()
    
    base_info = {
        "apply_id": apply_id,
        "product_type": PRODUCT_TYPE_SAAS,
        "sign_mode": SIGN_MODE_ELECTRONIC,
        "delegatee_sign_mode": SIGN_MODE_ELECTRONIC,
        "agreement_pic": "jlpay-test/managefile/2024/02/28/1709081506952_af4f376e39d64abeb5dfb8a0c6db0da7.png",
        "agent_id": "50720711",
        "qrcode_term_auto": "1",
        "contact_info": {
            "contact_type": CONTACT_TYPE_LEGAL_PERSON,
            # 以下敏感字段在实际使用中需要填写
            # "contact_name": "王一",
            # "contact_phone": "13800138000",
            # "contact_id_no": "替换为身份证号"
        }
    }
    return base_info

def build_identification_info():
    """构建商户身份信息"""
    identification_info = {
        "merch_type": MERCH_TYPE_ENTERPRISE,
        "license_info": {
            "license_type": "02",  # 企业
            "license_name": "营业执照上的名称",
            "license_no": "91330108MABTT5NP6U",
            "period_begin": "2024-01-01",
            "period_end": "2030-01-01",
            "license_pic": "jlpay-test/managefile/2024/02/28/1709081506952_af4f376e39d64abeb5dfb8a0c6db0da7.png",
            "business_scope": "经营范围"
        },
        "identity_info": {
            "id_doc_type": "01",  # 身份证
            "id_card_name": "王一",
            "id_card_no": "110101199003077758",
            "legal_person_phone": "13800138000",
            "card_period_begin": "2024-01-01",
            "card_period_end": "2030-01-01",
            "id_card_address": "住址",
            "id_card_copy": "jlpay-test/managefile/2024/02/28/1709081474283_7ddfb60f42d94f8094ec88d7c78ec4a3.png",
            "id_card_national": "jlpay-test/managefile/2024/02/28/1709081506952_af4f376e39d64abeb5dfb8a0c6db0da7.png",
        }
    }
    return identification_info

def build_business_info():
    """构建商户经营信息"""
    business_info = {
        "merch_shortname": "商户经营名称",
        "mcc_code": "5311",
        "address_code": "440305",
        "address_detail": "深圳市南山区工业一路22501号",
        "door_pic": "jlpay-test/managefile/2024/02/28/1709081506952_af4f37.png",
        "indoor_pic": "jlpay-test/managefile/2024/02/28/1709081506952_af4f37.png",
        "cashier_pic": "jlpay-test/managefile/2024/02/28/1709081506952_af4f37.png",
    }
    return business_info

def build_settlement_info():
    """构建商户结算账户信息"""
    settlement_info = {
        "settle_type": SETTLE_TYPE_LEGAL_PERSON_CARD,
        "settle_relation": SETTLE_RELATION_BRANCHES,
        "account_info": {
            "account_no": "6227001215950896532",
            "account_name": "王一",
            "cert_type": "01",  # 身份证
            "bank_code": "082",
            "bank_branch_id": "105584000370",
            "bank_branch_name": "中国建设银行股份有限公司深圳罗湖支行",
            "account_pic": "jlpay-test/managefile/2024/02/28/1709106666879_6c53af86b9654680a727b92795dce6c2.jpg",
        },
        "other_info": {
            "identity_face_pic": "jlpay-test/managefile/2024/02/28/1709106666879_6c53af86b9654680a727b92795dce6c2.jpg"
        }
    }
    return settlement_info

def build_rate_info(fee_calc_type, rate, min_amt="0", max_amt="-1", fixed="0", bottom="0", top="-1", step="0", base_amount="0", base_fee="0"):
    """
    构建费率信息条目
    
    Args:
        fee_calc_type: 费用计算类型代码
        rate: 费率百分比
        min_amt: 最小金额
        max_amt: 最大金额，"-1"表示不限
        fixed: 固定费用
        bottom: 保底费用
        top: 封顶费用，"-1"表示不封顶
        step: 阶梯
        base_amount: 基础金额
        base_fee: 基础费用
    
    Returns:
        费率信息字典
    """
    return {
        "fee_calc_type": fee_calc_type,
        "rate": rate,
        "min_amt": min_amt,
        "max_amt": max_amt,
        "fixed": fixed,
        "bottom": bottom,
        "top": top,
        "step": step,
        "base_amount": base_amount,
        "base_fee": base_fee
    }

def build_settlement_rule():
    """构建商户结算规则和费率规则"""
    # 费率信息列表
    rate_info = [
        # 微信支付宝相关费率
        build_rate_info("30", "0.38"),  # 微信
        build_rate_info("31", "0.38"),  # 支付宝
        build_rate_info("03", "0.38", max_amt="100000"),  # 银联二维码
        
        # 银联内卡费率
        build_rate_info("01", "0.45", top="1900"),  # 银联内卡借记卡 (封顶19元)
        build_rate_info("02", "0.55"),  # 银联内卡贷记卡 (不封顶)
        
        # 银联外卡费率
        build_rate_info("11", "0.45", top="1900"),  # 银联外卡借记卡
        build_rate_info("12", "0.55"),  # 银联外卡贷记卡
        
        # 外币支付相关费率
        build_rate_info("20", "0.60"),  # 外币DCC
        build_rate_info("21", "0.60"),  # 外币EDC
        build_rate_info("22", "0.60"),  # 外币EDC-VM
        build_rate_info("23", "0.55"),  # 外币EDC优惠-VM
        
        # 支付宝优享相关费率
        build_rate_info("34", "0.38", top="1900"),  # 支付宝优享借记卡
        build_rate_info("35", "0.40"),  # 支付宝优享贷记卡
        
        # 万事网联相关费率
        build_rate_info("60", "0.38", top="1900"),  # 万事网联非接优惠
        build_rate_info("61", "0.45", top="1900"),  # 万事网联借记卡
        build_rate_info("62", "0.55"),  # 万事网联贷记卡
        
        # 快速提现费率
        build_rate_info("T0", "0.10", bottom="100"),  # 快速提现 (保底1元)
    ]
    
    settlement_rule = {
        "settle_info": {
            "settle_mode": "7",  # 仅D1，资金在交易完成第二个自然日结算
            "day_cut": "000000",  # 账单日切点为昨天0点到今天0点
            "settle_session": "040000",  # 4点付款
            "account_change_flag": "0",  # 不允许商户后台变更结算账户
        },
        "rate_info": rate_info
    }
    return settlement_rule

def build_additional_info():
    """构建其他附加信息"""
    additional_info = {
        "report_info": {
            # 可按需添加以下字段
            # "wechat_jsapi_path": "https://xxx.com/pay/",
            # "wechat_sub_appid": "wx1234567890",
            # "wechat_pid": "12345678",
            # "alipay_pid": "12345678",
        }
    }
    return additional_info

def build_sms_config():
    """构建短信配置"""
    sms_config = {
        # 可按需添加以下字段
        # "merch_login_notify": "1",
        # "withdraw_password_notify": "1",
        # "sign_notify": "1",
        # "realname_notify": "1"
    }
    return sms_config

def build_func_info():
    """构建商户业务功能配置"""
    func_info = {
        # 可按需添加以下字段
        # "open_functions": ["01", "02"]
    }
    return func_info

def build_chain_store_info():
    """构建品牌连锁商户进件配置信息"""
    chain_store_info = {
        # 可按需添加以下字段
        # "level": "1",
        # "main_merch_no": "12345678",
        # "at_mode": "0"
    }
    return chain_store_info

def build_brand_info():
    """构建品牌信息"""
    brand_info = {
        # 可按需添加以下字段
        # "brand_name": "XX品牌",
        # "brand_mark_pic": "jlpay-test/managefile/2024/02/28/1709081506952_af4f37.png",
        # "brand_auth_pic": "jlpay-test/managefile/2024/02/28/1709081506952_af4f37.png",
        # "contact_name": "王一",
        # "contact_phone": "13800138000"
    }
    return brand_info

# =================== 示例函数 =====================
def merchant_incoming_add_demo():
    """商户进件示例"""
    logger.info("开始执行商户进件示例")
    
    # 创建配置对象和商户服务
    config = create_config()
    merchant_service = MerchantService(config)
    
    # 创建商户进件请求
    request = MerchantIncomingAddRequest()
    
    # 设置各项信息
    request.set_base_info(build_base_info())
    request.set_identification_info(build_identification_info())
    request.set_business_info(build_business_info())
    request.set_settlement_info(build_settlement_info())
    request.set_settlement_rule(build_settlement_rule())
    request.set_additional_info(build_additional_info())
    request.set_sms_config(build_sms_config())
    request.set_func_info(build_func_info())
    # request.set_chain_store_info(build_chain_store_info())
    # request.set_brand_info(build_brand_info())
    
    # 发送请求
    response = send_request_and_handle_response(merchant_service, request, "商户进件")
    
    # 处理响应结果
    if response and response.is_success():
        logger.info(f"商户进件成功！")
        logger.info(f"响应报文：{response.to_dict()}")
    else:
        logger.error("商户进件失败")
        if response:
            logger.error(f"响应报文：{response.to_dict()}")
    
    logger.info("商户进件示例执行完毕")


def merchant_incoming_modify_demo():
    """商户进件修改示例"""
    logger.info("开始执行商户进件修改示例")
    
    # 创建配置对象和商户服务
    config = create_config()
    merchant_service = MerchantService(config)
    
    # 创建商户进件修改请求
    request = MerchantIncomingModifyRequest()
    
    # 设置各项信息，复用大部分build_*函数
    request.set_base_info(build_base_info(is_modify=True))
    request.set_identification_info(build_identification_info())
    
    # 可以覆盖部分信息进行修改
    business_info = build_business_info()
    business_info["merch_shortname"] = "深圳市泰思便利店"  # 修改商户名称
    request.set_business_info(business_info)
    
    request.set_settlement_info(build_settlement_info())
    request.set_settlement_rule(build_settlement_rule())
    request.set_additional_info(build_additional_info())
    request.set_sms_config(build_sms_config())
    request.set_func_info(build_func_info())
    # request.set_chain_store_info(build_chain_store_info())
    # request.set_brand_info(build_brand_info())
    
    # 发送请求
    send_request_and_handle_response(merchant_service, request, "商户进件修改")
    
    logger.info("商户进件修改示例执行完毕")


def realname_query_demo():
    """微信支付宝认证查询示例"""
    logger.info("开始执行微信支付宝认证查询示例")
    
    # 创建配置对象和商户服务
    config = create_config()
    merchant_service = MerchantService(config)
    
    # 创建微信支付宝认证查询请求
    request = RealnameQueryRequest()
    
    # 设置请求参数
    request.set_merch_no("123456789012345")  # 示例商户号，替换为实际的商户号
    request.set_query_type("0")  # 0：申请单查询（默认）
    request.set_channel_type("00")  # 00：所有渠道(默认)
    
    # 发送请求
    response = send_request_and_handle_response(merchant_service, request, "微信支付宝认证查询")
    
    # 处理详细的响应信息
    if response and response.is_success() and response.realname_info:
        logger.info("\n认证信息列表:")
        for info in response.realname_info:
            channel_type = info.get('channel_type')
            channel_name = "微信" if channel_type == "01" else "支付宝" if channel_type == "02" else "未知"
            
            logger.info(f"\n{channel_name}认证信息:")
            logger.info(f"渠道类型: {channel_type}")
            
            # 申请单查询结果
            if request.query_type == "0":
                applyment_status = info.get('applyment_status')
                status_desc = {
                    "1": "审核中",
                    "2": "待确认联系信息",
                    "3": "待账户验证",
                    "4": "审核通过",
                    "5": "审核驳回",
                    "6": "已冻结",
                    "7": "已作废",
                    "200": "已授权"
                }.get(applyment_status, "未知状态")
                
                logger.info(f"申请状态: {applyment_status} - {status_desc}")
                
                if info.get('qrcode_data'):
                    logger.info(f"二维码URL: {info.get('qrcode_data')}")
                
                if applyment_status == "5":  # 审核驳回
                    logger.info(f"驳回字段: {info.get('reject_param')}")
                    logger.info(f"驳回原因: {info.get('reject_reason')}")
            
            # 授权结果查询
            elif request.query_type == "1":
                authorize_state = info.get('authorize_state')
                auth_desc = "已授权" if authorize_state == "200" else "未授权" if authorize_state == "201" else "未知"
                logger.info(f"授权状态: {authorize_state} - {auth_desc}")
    
    logger.info("微信支付宝认证查询示例执行完毕")


if __name__ == "__main__":
    logger.info("=" * 50)
    logger.info("===== 商户进件示例 开始 =====")
    logger.info("=" * 50)
    merchant_incoming_add_demo()
    
    logger.info("\n" + "=" * 50)
    logger.info("===== 商户进件修改示例 开始 =====")
    logger.info("=" * 50)
    merchant_incoming_modify_demo()
    
    logger.info("\n" + "=" * 50)
    logger.info("===== 微信支付宝认证查询示例 开始 =====")
    logger.info("=" * 50)
    realname_query_demo()
    
    logger.info("\n" + "=" * 50)
    logger.info("===== 所有示例执行完毕 =====")
    logger.info("=" * 50)